package com.chat.simplechat.websocket;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.chat.simplechat.constant.WebSocketConstant;
import com.chat.simplechat.entity.LoginUser;
import com.chat.simplechat.event.UserGoOnlineEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * 长连接
 * @author wangyabin
 * @date 2022/10/28 17:34
 */
@Slf4j
@Component
public class SpringWebSocket implements WebSocketHandler {

    @Resource
    private ApplicationContext applicationContext;
    
    private LoginUser loginUser;
    
    private String userId;
    
    private static CopyOnWriteArraySet<WebSocketSession> webSocketSessions;

    static {
        webSocketSessions = new CopyOnWriteArraySet<>();
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        LoginUser user =
                (LoginUser) session.getAttributes().get(WebSocketConstant.LOGIN_USER);
        this.loginUser = user;
        this.userId = user.getUserId();
        webSocketSessions.add(session);
        applicationContext.publishEvent(new UserGoOnlineEvent(this,user));
        log.info("[WebSocket]:用户[{}]已连接，当前在线用户数量:[{}]",user.getUsername(),webSocketSessions.size());
    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        String msg = (String) message.getPayload();
        JSONObject jsonObject = JSON.parseObject(msg);
        if(jsonObject.get("code").equals("0")){
            log.info("[WebSocket]:客户端心跳");
            jsonObject.put("connect",true);
            TextMessage textMessage = new TextMessage(jsonObject.toJSONString());
            session.sendMessage(textMessage);
            return;
        }
        LoginUser user = (LoginUser) session.getAttributes().get("LOGIN_USER");
        //真实消息
        jsonObject.put("content",jsonObject.get("contentText"));
        jsonObject.put("comeFrom",user.getUsername());
        String userId = (String) jsonObject.get("toUserId");
        this.readyMessage(userId,jsonObject.toJSONString());
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.info("[WebSocket]:传输错误，连接关闭！{}",exception);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        webSocketSessions.remove(session);
        log.info("[WebSocket]:用户[{}]连接断开，当前在线用户数量:[{}]",loginUser.getUsername(),webSocketSessions.size());
        log.info("断开连接状态码：{}",closeStatus);
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

    /**
     * 就绪消息
     * @param userId 用户ID
     * @param message 消息内容
     */
    public void readyMessage(String userId, String message) {
        for (WebSocketSession userSession : webSocketSessions) {
            if (userSession.getAttributes().get("USER_ID").equals(userId)) {
                this.sendMessage(userSession, message);
            }
        }
        log.info("[WebSocket]:消息发送成功");
    }

    /**
     * 发送消息
     * @param webSocketSession
     * @param message
     * @throws IOException
     */
    private boolean sendMessage(WebSocketSession webSocketSession,String message) {
        boolean sendSign = false;
        try {
            if(webSocketSession.isOpen()){
                TextMessage textMessage = new TextMessage(message);
                //发送
                webSocketSession.sendMessage(textMessage);
                sendSign = true;
            }else{
                log.error("[WebSocket]:用户[{}]未连接,消息[{}]推送失败",loginUser.getUsername(),message);
            }
        } catch (IOException e) {
            log.error("[WebSocket]:消息推送异常,内容：{}",message);
        }
        return sendSign;
    }

    /**
     * 获取在线用户
     * @return
     */
    public List<LoginUser> getOnlineUser(){
        List<LoginUser> loginUsers = new ArrayList<>();
        //当前在线用户
        for (WebSocketSession online : webSocketSessions) {
            if(online.getAttributes().get("USER_ID").equals(userId)){
                continue;
            }
            LoginUser user = (LoginUser) online.getAttributes().get("LOGIN_USER");
            loginUsers.add(user);
        }
        return loginUsers;
    } 
}
